var fc = new FacebookController();

function bubbleSort(dict){
	var values = [];
	var keys = [];

	var add;
	for(a in dict){
		add = false;
		for(var i=0;i<values.length;i++){
			if(values[i]==dict[a]) continue;
			if(dict[a]<values[i]){
				add=true;
				values.splice(i,0,dict[a])
				keys.splice(i,0,a);
				break;
			}
		}
		if(!add){
			values.push(dict[a]);
			keys.push(a);
		}
	}

	return [values,keys];
}

function analyseData(metrics){		
	var friendsCoef = {};
	for(x in metrics["likesCount"]){
		var coef =  metrics["likesCount"][x] * 4.0;
		if(metrics["sharesCount"][x]!=undefined) coef+= metrics["sharesCount"][x]*2.0;
		if(metrics["taggedCount"][x]!=undefined) coef+= metrics["taggedCount"][x]*2.0;
		if(metrics["mutualCount"][x]!=undefined) coef+= metrics["mutualCount"][x]*1.0; 
		if(metrics["commentsCount"][x]!=undefined) coef+= metrics["commentsCount"][x]*5.0; 
		if(metrics["inboxCount"][x]!=undefined) coef+= metrics["inboxCount"][x]*3.0; 

		var div = 17.0;

		friendsCoef[x] = coef/div;
	}

	if(control.debug) facebookDebug.metrics = metrics;
	return friendsCoef;
}

function analyseMessage(r){
	/*Cada r eh uma lista de objetos com as mensagens captadas para ua thread
		author_id: 100001521883282
		created_time: 1343839166
		message_id: "150993828359314_1"

		Fazer a analise em cima disso
	*/
	if(control.debug) console.log("MESSAGE",r);

	var today = (new Date()).getTime();
	var msgByAuthor = {};
	var totalMsgByAuthor = {};
	for(req in r){
		//if(r[req].data.length==1) continue;
		var msg = r[req].data;
		for(m in msg){
			var author = msg[m].anon;	/*Author is included as an anonymous campus in the query*/
			var msgNumber = msg[m].message_id.split("_")[1];
			if(msgByAuthor[author]==undefined) msgByAuthor[author] = {};
			msgByAuthor[author][msgNumber] = msg[m].created_time;
			totalMsgByAuthor[author] = msgNumber;
		}
	}


	var diffByAuthor = {};
	var totalAuthors=0;			
	var average = 0;
	for(u in msgByAuthor){
		var totalMsg = totalMsgByAuthor[u];
		var pt1 = msgByAuthor[u][1];
		var pt9 = msgByAuthor[u][totalMsg];

		/*Higher Frequency Contact Equation - An rect equation*/
		var hfce = function(x){
			var newPt9 = (today-pt1)*totalMsg/(pt9-pt1);
			return pt1 + x*(newPt9-pt1)/totalMsg;
		};

		diffByAuthor[u]=0;
		for(point in msgByAuthor[u]){
			diffByAuthor[u]+= Math.abs( (msgByAuthor[u][point] - hfce(point)) );
		}

		diffByAuthor[u]/=(pt9-pt1+totalMsg);
		average+=diffByAuthor[u];
		totalAuthors+=1;
	}
	average /=totalAuthors;

	/*Identifying and removing the outlets*/
	var dict = bubbleSort(diffByAuthor);
	var ord = dict[0];
	var authors = dict[1];

	var i = ord.length-1;
	while( ord[i]>average ){
		delete diffByAuthor[authors[i]];
		i-=1;
	}
	var maxDiff = ord[i];

	/*Normalizing the results*/
	for(u in msgByAuthor){
		if(diffByAuthor[u]==undefined) continue;
		diffByAuthor[u] = Math.abs( (diffByAuthor[u]-maxDiff)/maxDiff );
	}


	return {"inboxCount":diffByAuthor};
}

function analyseLikes(list){
	var metrics = {"likesCount":{},"sharesCount":{}};
	var myId = control.facebookId;

	var likeMax = 0;
	var likeMaxUserId=null;

	var shareMax=0;
	var shareMaxUserId=null;
	for(userId in list){
		if(metrics["likesCount"][userId]==undefined) metrics["likesCount"][userId]=0;
		if(metrics["sharesCount"][userId]==undefined) metrics["sharesCount"][userId]=0;			

		var likeCount = 0;
		var shareCount = 0;			
		for(entry in list[userId].data){
			if(list[userId].data[entry].likes!=undefined){
				if(list[userId].data[entry].type==="photo") continue;
				for(like in list[userId].data[entry].likes.data){
					if( list[userId].data[entry].likes.data[like]==null ) continue;
					if( list[userId].data[entry].likes.data[like].id == myId ){
						likeCount+=1;
						break;
					}
				}
			}	

			if(list[userId].data[entry].shares!=undefined){
				shareCount+=1;
			}		
		}

		metrics["likesCount"][userId] = likeCount;
		metrics["sharesCount"][userId] = shareCount;

		if(likeCount>likeMax){
			likeMax = likeCount;
			likeMaxUserId = userId;
		}		

		if(shareCount>shareMax){
			shareMax = shareCount;
			shareMaxUserId = userId;
		}		
	}

	if(likeMax==0) likeMax = 1;
	
	if(shareMax==0) shareMax = 1;					


	for(x in metrics["likesCount"] ){
		metrics["likesCount"][x] = metrics["likesCount"][x] / likeMax;
	}	

	for(x in metrics["sharesCount"] ){
		metrics["sharesCount"][x] = metrics["sharesCount"][x] / shareMax;
	}			

	return metrics;		
}

function analyseMutual(list){		
	var metrics = {"mutualCount":{}};
	var mutualMax=0;
	var mutualCount=0;
	var mutualMaxUserId=null;

	for(userId in list){				
		for(entry in list[userId].data){
			if(list[userId].data[entry].from!=undefined)continue;
			mutualCount = list[userId].data.length;

			if(mutualCount>mutualMax){
				mutualMax = mutualCount;
				mutualMaxUserId = userId;
			}				
		}
		metrics["mutualCount"][userId] = mutualCount;						
	}

	if(mutualMax==0) mutualMax = 1;				

	for(userId in list){
		metrics["mutualCount"][userId] = metrics["mutualCount"][userId]/mutualMax;
	}

	return metrics;
}

function analyseTagged(list){
	var taggedMax = 0;
	var taggedMaxUserId = null;
	var metrics = {"taggedCount":{}};
	for(level in list){
		for(post in list[level].data){
			if( list[level].data[post].from !=undefined ){
				var userId = list[level].data[post].from.id;

				if( metrics["taggedCount"][userId]==undefined ){
					metrics["taggedCount"][userId] = 0;
				}

				metrics["taggedCount"][userId]+=1;
				if(metrics["taggedCount"][userId]>taggedMax){
					taggedMax = metrics["taggedCount"][userId];
					taggedMaxUserId = userId;
				}
			}
		}
	}

	if(taggedMax==0) taggedMax = 1;

	for(x in metrics["taggedCount"] ){
		metrics["taggedCount"][x] = metrics["taggedCount"][x] / taggedMax;
	}		

	return metrics;				
}		

function analyseComments(list){
	var myId = control.facebookId;
	var commentsMax = 0;
	var commentsMaxUserId = null;
	var metrics = {"commentsCount":{}};
	for(userId in list){
		var commentsCount = 0;	
		for(post in list[userId].data){
			if(list[userId].data[post].comments==undefined) continue;
			if(list[userId].data[post].comments.data==undefined) continue;

			for(comment in list[userId].data[post].comments.data){
				if(list[userId].data[post].comments.data[comment].from==undefined) continue

				if(list[userId].data[post].comments.data[comment].from.id==myId){				

					commentsCount+=1;
					if(commentsCount>commentsMax){
						commentsMax = commentsCount;
						commentsMaxUserId = userId;
					}																	
					break;
				}
			}		
		}
		metrics["commentsCount"][userId] = commentsCount;		
	}

	if(commentsMax==0) commentsMax=1;
	
	for(x in metrics["commentsCount"] ){
		metrics["commentsCount"][x] = metrics["commentsCount"][x] / commentsMax;
	}				

	return metrics;
}

function collectFacebookData(callback_fn,progress_fn){
	var metrics = {};
	var counter=0;

	var taggedJob = new Job("Tagged JOB",5,function(r){		
		if(control.debug) facebookDebug.outAnalyseTagged = r;
		var dict = analyseTagged(r);		

		for(x in dict){
			metrics[x] = dict[x];
		}
		counter+=1;
	});

	var mutualJob = new Job("Mutual JOB",5,function(r){
		var joinList = {}
		for(var i=0;i<r.length;i++){
			for(x in r[i]){
				joinList[x] = r[i][x];
			}
		}

		if(control.debug) facebookDebug.outAnalyseMutual = joinList;
		var dict = analyseMutual(joinList);

		for(x in dict){
			metrics[x] = dict[x];
		}		
		counter+=1;
	})

	var postsJob = new Job("Posts JOB",50,function(r){
		var joinList = {};

		for(var i=0;i<r.length;i++){
			for(x in r[i]){
				joinList[x] = r[i][x];
			}
		}

		if(control.debug) facebookDebug.outAnalyseLike = joinList;
		var dict = analyseLikes(joinList);
		for(x in dict){
			metrics[x] = dict[x];
		}

		var dict = analyseComments(joinList);
		if(control.debug) facebookDebug.outAnalyseComment = joinList;
		for(x in dict){
			metrics[x] = dict[x];
		}		

		counter+=1;
	});

	var messageJob = new Job("Message JOB",30,function(r){
		if(control.debug) facebookDebug.outAnalyseMessage = r;
		var dict = analyseMessage(r);	
		if(control.debug) facebookDebug.messageCoefs = dict;

		for(x in dict){	
			metrics[x] = dict[x];
		}		

		var usersId = [];
		for(u in dict["inboxCount"]){
			usersId.push(u);
		}

		divideUserRequests(2,usersId,postsJob,PostBatchRequest);
		postsJob.run();

		mutualJob.addAction( new MutualBatchRequest(0,usersId,0,usersId.length) );
		mutualJob.run();		

		counter+=1;
	});


	var threadJob = new Job("Thread JOB",10,function(r){
		if(control.debug) facebookDebug.outAnalyseThread = r;

		for(x in r[0].data){
			var author = null;
			for(n in r[0].data[x].recent_authors){
				if(r[0].data[x].recent_authors[n]!=control.facebookId){
					author = r[0].data[x].recent_authors[n];
					break;
				}
			}
			if(author!=null)
				messageJob.addAction( new MessageBatchRequest(0,author,r[0].data[x].thread_id,r[0].data[x].message_count) );
		}
		
		messageJob.run();
		counter+=1;
	});	

	threadJob.addAction( new ThreadBatchRequest(0) );
	threadJob.run();	

	taggedJob.addAction( new TaggedBatchRequest(0,null,null,null) );
	taggedJob.run();	

	var checkProgress = function(lj){
		var total = 0;
		var complete = true;
		for(var i=0;i<lj.length;i++){
			total+=lj[i].getPerc();
			if(lj[i].running()) complete = false;
		}

		if(complete){
			total = 100;
			if(counter==5){				
				callback_fn( analyseData(metrics) );	
				progress_fn(total);				
				return;
			}			
		}
		progress_fn(total);
		window.setTimeout(function(){checkProgress(lj);},1000);
	};

	checkProgress([taggedJob,postsJob,mutualJob,messageJob,threadJob]);
}





function getBasicInfo(usersId,callback_fn){
	/*Since it is just a simple and not heavy request, I am not
	using the JOB Batch structure to control the flow of data*/

	var usersStr = "";
	for(var i=0;i<usersId.length;i++){
		usersStr += usersId[i] + ",";
	}	
	usersStr = usersStr.substring(0,usersStr.length-1);
	if(control.debug) console.log("BASIC INFO",usersStr);

	
	FB.api("/?ids="+usersStr+"&fields=id,first_name,name,gender,locale,picture",function(r){
		var l = []
		for(x in r){
			r[x].picture = "https://graph.facebook.com/" + x + "/picture?type=large";
			l.push(r[x]);
		}
		callback_fn(l);
	});
	
}

function facebookLogin(callback_fn){
    login(callback_fn);
}

function login(callback_fn) {
    FB.login(function(response) {
        if (response.authResponse) {
        	FB.api("/me",function(response){
        		control.facebookId = response.id;
        		callback_fn(true);	
        	});            
        } else {
            callback_fn(false);
        }
    },{"scope":"read_mailbox"});
}		
